#ifndef XLIST_H
#define XLIST_H
/************************************************
  * 描述: LINQ工具类的实现
  * File: xlist.hpp
  * Author: qijiangyong@mozihealthcare.cn
  * Date: 2025-07-25
  * Update: 2025-09-02
  ***********************************************/
#include <iostream>
#include <iterator>
#include <algorithm>
#include <stdexcept>
#include <type_traits>
#include <tuple>
#include <any>

#include <QMap>
#include <QHash>
#include <QList>
#include <QDateTime>
#include <QLinkedList>
#include <QDebug>

namespace xlist
{
template <class T>
class XList
{
public:
    XList() { m_list.clear(); }
    XList(const XList<T>& t) : m_list(t.m_list) {}
    XList(const QList<T>& t) : m_list(t) {}
    XList& operator=(const XList& other)
    {
        if (this == &other)
            return *this;
        //.
        this->m_list = other.m_list;

        return *this;
    }
    // add
    void Add(const T& item)
    {
        m_list.push_back(item);
    }
    // print[test] need overload <<
    void print(void)
    {
        for (const auto& item : m_list)
            std::cout << "item -- " << item << std::endl;
    }
    void printByQt(void)
    {
        for (const auto& item : m_list)
            qDebug() << "[qt]item --" << item;
    }
    // tolist
    const QList<T>& ToList(void) const
    {
        return m_list;
    };
	// size
	// int size() const
	// {
	// 	return m_list.size();
	// }
    // where by condition
    template <typename Predicate>
    auto Where(Predicate p)
    {
        if (!hasOk())return *this;
        //.
        QList<T> newList;
        std::copy_if(m_list.begin(), m_list.end(),
                     std::back_inserter(newList), p);

        return XList<T>(newList);
    }
    // select[filter specific fields]
    template <typename Transform>
    auto Select(Transform transformer) -> XList<decltype(transformer(std::declval<T>()))>
    {
        using U = decltype(transformer(std::declval<T>()));

        XList<U> result;
        for (const auto& item : m_list)
        {
            result.Add(transformer(item));
        }

        return result;
    }    
    // 获取第一个元素（集合为空时抛异常）
    T First()
    {
        try {
            return checkedGet(0);

        } catch (const std::out_of_range& e) {
            qWarning() << "Access failed:" << e.what();
            return T();
        }
    }
    // 获取第一个元素，集合为空返回默认值
    auto FirstOrDefault()
    {
        return checkedGet(0, true);
    }
    // 获取第一个匹配的元素（没有匹配项抛异常）
    template <typename Predicate>
    T First(Predicate p)
    {
        try {
            return findFirstElement(p);

        } catch (const std::out_of_range& e) {
            qWarning() << "find failed:" << e.what();
            return T();
        }
    }
    // 获取第一个匹配的元素，没有匹配项则返回默认值
    template <typename Predicate>
    auto FirstOrDefault(Predicate p)
    {
        return findFirstElement(p, true);
    }
    // 获取唯一元素（没有或多个元素都抛异常）
    T Single()
    {
        try {
            return findSingleElement();

        } catch (const std::out_of_range& e) {
            qWarning() << "Find failed:" << e.what();
            return T();
        }
    }
    // 获取唯一元素，没有匹配项返回默认值、多个匹配则抛异常
    auto SingleOrDefault()
    {
        try {
            return findSingleElement(true);

        } catch (const std::out_of_range& e) {
            qWarning() << "Find failed:" << e.what();
            return T();
        }
    }
    // 获取唯一匹配项（没有或多个匹配都抛异常）
    template <typename Predicate>
    T Single(Predicate p)
    {
        try {
            return findSingleElement(p);

        } catch (const std::out_of_range& e) {
            qWarning() << "Find failed:" << e.what();
            return T();
        }
    }
    // 获取唯一匹配项，没有匹配项返回默认值、多个匹配则抛异常
    template <typename Predicate>
    auto SingleOrDefault(Predicate p)
    {
        try {
            return findSingleElement(p, true);

        } catch (const std::out_of_range& e) {
            qWarning() << "Find failed:" << e.what();
            return T();
        }
    }
    // 获取最后一个元素（集合为空时抛异常）
    T Last()
    {
        try {
            return checkedGet(m_list.size() - 1);

        } catch (const std::out_of_range& e) {
            qWarning() << "Access failed:" << e.what();
            return T();
        }
    }
    // 获取最后一个元素，集合为空返回默认值
    auto LastOrDefault()
    {
        return checkedGet(m_list.size() - 1, true);
    }
    // 判断是否存在元素【即是否非空】
    bool Any()
    {
        return !m_list.isEmpty();
    }
    // 判断是否存在匹配项
    template <typename Predicate>
    bool Any(Predicate p)
    {
        if (!hasOk())
            return false;
        //.
        auto iter = std::find_if(m_list.begin(), m_list.end(), p);
        return iter != m_list.end();
    }
    // 判断是否全部满足条件
    template <typename Predicate>
    bool All(Predicate p)
    {
        if (!hasOk())
            return false;
        //.
        XList<T> newList = Where(p);
        return newList.listSize() == listSize();
    }
    // 判断是否包含某个元素，依赖 Equals() 和 GetHashCode()
    bool Contains(const T& element)
    {
        if (!hasOk())
            return false;
        //.
        return m_list.contains(element);
    }
    // 去重（去除重复项）,
    // 需要确保 T 类型重写了 Equals() 和 GetHashCode()，或使用自定义比较器。
    XList<T> Distinct()
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> uniqueList;

        QSet<T> seen;
        for (const auto& item : m_list) {
            if (!seen.contains(item)) {
                seen.insert(item);
                uniqueList.append(item);
            }
        }

        return uniqueList;
    }
    // distinct override
    template <typename Predicate>
    XList<T> Distinct(Predicate p)
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> uniqueList;

        QSet<decltype(p(T{}))> seen;
        for (const T& item : m_list) {
            auto key = p(item);
            if (!seen.contains(key)) {
                seen.insert(key);
                uniqueList.append(item);
            }
        }

        return uniqueList;
    }
    // 升序排序，返回排序后的序列
    XList<T> OrderBy()
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> result(m_list);
        std::sort(result.begin(), result.end());

        return result;
    }
    // orderby override
    template <typename Predicate>
    XList<T> OrderBy(Predicate p)
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> result(m_list);
        std::sort(result.begin(), result.end(), p);

        return result;
    }
    // 降序排序，返回降序排列的序列
    XList<T> OrderByDescending()
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> result(m_list);
        std::sort(result.begin(), result.end(), std::greater<T>());

        return result;
    }
    // orderbydescending override
    template <typename Predicate>
    XList<T> OrderByDescending(Predicate p)
    {
        if (!hasOk())return *this;
        //.
        if (1 == listSize())return *this;
        //.
        QList<T> result(m_list);
        std::sort(result.begin(), result.end(), p);

        return result;
    }
    // 合并两个序列，保留重复项
    XList<T> Concat(const XList<T>& other)
    {
        if (!hasOk())
        {
            if (other.ToList().isEmpty())
                return *this;
            else
                return other;
        }
        else
        {
            if (other.ToList().isEmpty())
                return *this;
        }
        //.
        QList<T> merged = m_list + other.m_list;
        return merged;
    }
    // 合并并去重，去除重复项、需实现Equals
    XList<T> Union(const XList<T>& other)
    {
        QList<T> result;
        QSet<T> seen;

        // 先处理自已
        for (const auto& item : m_list) {
            if (!seen.contains(item)) {
                seen.insert(item);
                result.append(item);
            }
        }

        // 再处理 other
        for (const auto& item : other.ToList()) {
            if (!seen.contains(item)) {
                seen.insert(item);
                result.append(item);
            }
        }

        return result;
    }
    // 按指定键分组
    // use like : auto grouped = GroupBy(people, [](const Person& p) { return p.age; });
    template <typename Key>
    QList< QPair< decltype(std::declval<Key>()(std::declval<T>())), QList<T> > > GroupBy(Key k)
    {
        if (!hasOk())return {};
        //.
        QList< QPair< decltype(k(T{})), QList<T> > > result;
        QMap<decltype(k(T{})), int> keyToIndex; // key → result 中的索引

        for (const T& item : m_list) {
            auto key = k(item);
            auto it = keyToIndex.find(key);

            if (it != keyToIndex.end()) {
                // 已存在该组，直接添加到对应列表
                result[it.value()].second.append(item);
            } else {
                // 新组，创建并记录索引
                QList<T> newList;
                newList.append(item);
                result.append({key, newList});
                keyToIndex[key] = result.size() - 1; // 当前索引
            }
        }

        return result;
    }
    // 转换为字典，以指定键生成字典[只指定key]
    template <typename Key>
    QHash<decltype(std::declval<Key>()(std::declval<T>())), T> ToDictionary(Key k)
    {
        if (!hasOk())return {};
        //.
        QHash<decltype(k(T{})), T> result;
        for (const T& item : m_list)
        {
            if (result.contains(k(item)))
            {
                throw std::invalid_argument("invalid argument key!");
            }
            result[k(item)] = item;
        }

        return result;
    }
    // 转换为字典，以指定键生成字典[同时指定key与val]
    template <typename Key, typename Val>
    QHash<decltype(std::declval<Key>()(std::declval<T>())),
        decltype(std::declval<Val>()(std::declval<T>()))> ToDictionary(Key k, Val v)
    {
        if (!hasOk())return {};
        //.
        QHash<decltype(k(T{})), decltype(v(T{}))> result;
        for (const T& item : m_list)
        {
            if (result.contains(k(item)))
            {
                throw std::invalid_argument("invalid argument key!");
            }
            result[k(item)] = v(item);
        }

        return result;
    }

private:
    // 是否非空
    bool hasOk(void) { return !m_list.isEmpty(); }
    // 根据类型返回默认值
    inline /*std::any*/auto valueBytype(void)
    {
        if constexpr (std::is_pointer_v<T>)
                return static_cast<T>(nullptr);
        else if constexpr (std::is_same_v<T, int> || std::is_integral_v<T>)
                return 0;
        else if constexpr (std::is_same_v<T, double> || std::is_floating_point_v<T>)
                return 0.00;
        else if constexpr (std::is_same_v<T, bool>)
                return 0;
        else if constexpr (std::is_enum_v<T>)
                return 0;
        else if constexpr (std::is_same_v<T, QDateTime>)
                return QDateTime();
        else if constexpr (std::is_class_v<T> || (std::is_trivial_v<T> && std::is_standard_layout_v<T>))
                return T();
        else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, QString>)
                return "";
        else if constexpr (std::is_object_v<T> || std::is_same_v<T, QObject>)
                return 0;

        return T();
    }
    /**
     * @brief checkedGet : 安全访问函数
     * @param index : 下标
     * @param bdef : 是否返回默认值
     */
    inline auto checkedGet(int index, bool bdef = false)
    {
        if (!hasOk())
        {
            if (!bdef)
            {
                throw std::out_of_range("list is empty!");
            }
            else
            {
                return valueBytype();
            }
        }
        if (index < 0 || index >= m_list.size()) {
            throw std::out_of_range(
                        QString("list index %1 out of range [0, %2)")
                        .arg(index).arg(m_list.size()).toStdString()
                        );
        }
        return m_list[index];
    }
    /**
     * 元素查找函数[返回满足条件的第一个元素]
     */
    template <typename Predicate>
    inline auto findFirstElement(Predicate p, bool bdef = false)
    {
        if (!hasOk())
        {
            if (!bdef)
            {
                throw std::out_of_range("list is empty!");
            }
            else
            {
                return valueBytype();
            }
        }
        auto iter = std::find_if(m_list.begin(), m_list.end(), p);
        if (iter == m_list.end())
        {
            if (!bdef)
                throw std::out_of_range("element not found!");
            else
                return valueBytype();
        }
        return *iter;
    }
    /**
     * 获取唯一元素[返回满足条件的第一个元素]
     */
    template <typename Predicate>
    inline auto findSingleElement(Predicate p, bool bdef = false)
    {
        if (!hasOk())
        {
            if (!bdef)
            {
                throw std::out_of_range("list is empty!");
            }
            else
            {
                return valueBytype();
            }
        }
        // process
        XList<T> result = Where(p);
        bool find = result.hasOk();
        if (!bdef)
        {
            if (find)
            {
                if (result.listSize() > 1)
                    throw std::out_of_range("multiple element!");
                else
                    return result.First();
            }
            else
                throw std::out_of_range("non single element!");
        }
        else
        {
            if (find)
            {
                if (result.listSize() > 1)
                    throw std::out_of_range("multiple element!");
                else
                    return result.First();
            }
            else
                return valueBytype();
        }
    }
    // findSingleElement重载
    inline auto findSingleElement(bool bdef = false)
    {
        if (!hasOk())
        {
            if (!bdef)
            {
                throw std::out_of_range("list is empty!");
            }
            else
            {
                return valueBytype();
            }
        }
        // process
        T firstElement;
        bool find = false;
        QHash<T, int> frequency;

        // 第一次遍历：统计每个元素的出现次数
        for (const T& element : m_list) {
            frequency[element]++;
        }

        // 第二次遍历：找到第一个出现次数为1的元素
        for (const T& element : m_list) {
            if (frequency.value(element) == 1) {
                firstElement = element;
                find = true;
                break;
            }
        }
        // 统计 value == 1 的个数
        int count = std::count_if(frequency.begin(), frequency.end(),
                                  [](const int& value) {
                                      return value == 1;
                                  });
        if (!bdef)
        {
            if (find)
            {
                if (count > 1)
                    throw std::out_of_range("multiple element!");
                else
                    return firstElement;
            }
            else
                throw std::out_of_range("non single element!");
        }
        else
        {
            if (find)
            {
                if (count > 1)
                    throw std::out_of_range("multiple element!");
                else
                    return firstElement;
            }
            else
                return valueBytype();
        }
    }
    // 获取列表大小
    inline int listSize() const
    {
        return m_list.size();
    }

private:
    QList<T> m_list;    
};

// 简洁版：用户负责写 s.xxx
#define SELECT_FIELDS(...) \
    [](const auto& s) { return std::make_tuple(__VA_ARGS__); }

// 可选：带类型版本
#define SELECT_FIELDS_OF(Type, ...) \
    [](const Type& s) { return std::make_tuple(__VA_ARGS__); }

// 可选：所有字段[需要自定义tie()方法，属于侵入式，更好的方式推荐Boost.PFR]
#define SELECT_ALL() [](const auto& s) { return s.tie(); }
// #define SELECT_ALL() [](const auto& s) { return boost::pfr::structure_tie(s); }

// 为 std::tuple 添加输出
template <typename Tuple, std::size_t... I>
void print_tuple(std::ostream& os, const Tuple& t, std::index_sequence<I...>)
{
    ((os << (I == 0 ? "" : ", ") << std::get<I>(t)), ...);
}

template <typename... Args>
std::ostream& operator<<(std::ostream& os, const std::tuple<Args...>& t)
{
    os << "(";
    print_tuple(os, t, std::index_sequence_for<Args...>{});
    os << ")";
    return os;
}
// for qt
inline QDebug operator<<(QDebug debug, const std::string& s)
{
    debug.nospace() << s.c_str();
    return debug;
}
inline QDebug operator<<(QDebug debug, const std::string_view& sv)
{
    debug.nospace() << QString::fromUtf8(sv.data(), sv.size());
    return debug;
}
template <std::size_t Index = 0, typename... Args>
void print_tuple_to_qdebug(QDebug& debug, const std::tuple<Args...>& t)
{
    if constexpr (Index == 0) {
        debug << "(";
    }

    debug.nospace() << std::get<Index>(t);

    if constexpr (Index + 1 == sizeof...(Args)) {
        debug << ")";
    } else {
        debug << ", ";
        print_tuple_to_qdebug<Index + 1>(debug, t);
    }
}
// 重载 QDebug << tuple
template <typename... Args>
QDebug operator<<(QDebug debug, const std::tuple<Args...>& t)
{
    debug.nospace(); // 避免自动加空格
    print_tuple_to_qdebug(debug, t);
    return debug;
}
}

#endif // XLIST_H
